-- card: 2946 from stack: in.3 -- bmap block id: 6031 -- flags: 4000 -- background id: 8327 -- name: XScrollBox ----- HyperTalk script ----- on Install get ChooseTargetStack() InstallResource XFCN,XScrollBox,it InstallResource DITL,XScrollBox,it InstallResource DLOG,XScrollBox,it end Install -- part 2 (field) -- low flags: 01 -- high flags: 4007 -- rect: left=384 top=58 right=286 bottom=491 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 3 -- text size: 9 -- style flags: 0 -- line height: 12 -- part name: scroller -- part 3 (button) -- low flags: 00 -- high flags: 8003 -- rect: left=76 top=298 right=320 bottom=176 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: XScrollBox ----- HyperTalk script ----- on mouseUp get XScrollBox("baker","Choose one of these:",card field "scroller","Help") go this card if it is "Help" then answer "You pushed the 'Help' button." else if it is "cancel" then answer "You pushed the 'Cancel' button." else if it is empty then answer "You did not select anything." else answer "Your choice was: " & it end if end mouseUp -- part 5 (field) -- low flags: 01 -- high flags: 2007 -- rect: left=17 top=31 right=286 bottom=382 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 3 -- text size: 10 -- style flags: 0 -- line height: 13 -- part name: Documentation -- part 7 (field) -- low flags: 81 -- high flags: 0007 -- rect: left=18 top=31 right=290 bottom=489 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 3 -- text size: 10 -- style flags: 0 -- line height: 13 -- part name: Source1 -- part 11 (field) -- low flags: 81 -- high flags: 0007 -- rect: left=18 top=31 right=290 bottom=489 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 0 -- font id: 3 -- text size: 10 -- style flags: 0 -- line height: 13 -- part name: Source2 -- part 12 (button) -- low flags: 00 -- high flags: A003 -- rect: left=289 top=298 right=320 bottom=458 -- title width / last selected line: 0 -- icon id / first selected line: 0 / 0 -- text alignment: 1 -- font id: 0 -- text size: 12 -- style flags: 0 -- line height: 16 -- part name: Show C Source: part 1 ----- HyperTalk script ----- on mouseUp if the short name of me is "Show C Source: part 1" then set the visible of card field "source1" to true set the visible of card field "source2" to false set the name of me to "Show C Source: part 2" else if the short name of me is "Show C Source: part 2" then set the visible of card field "source2" to true set the visible of card field "source1" to false set the name of me to "Hide C Source" else set the visible of card field "source2" to false set the visible of card field "source1" to false set the name of me to "Show C Source: part 1" end if end mouseUp -- part contents for card part 2 ----- text ----- able baker charlie dog ernest fox gamma horse ice cream jumping jack flash knockwurst liver monkey no way, jose occularity penelope qwerty rapscallion salubrious twinkle toes underwhelmed vermin wascally wabbit yokel zenzational -- part contents for card part 5 ----- text ----- XScrollBox version 2.4 Roger Brown XScrollBox is a HyperCard XFCN that creates a scrolling selection dialog box from any multi-lined container. Each line of the container is made into a selection line in the dialog. Only one line can be selected. The return value has two items: the number of the selection and the text of the selection. These are separated by commas as in normal HyperCard format. Selection can be made by : 1. double-clicking on a line. 2. single-clicking on a line, then pressing the OK button. 3. single-clicking on a line, then pressing the Return key. 4. typing the first letter(s) of a selection, then doing 1,2, or 3. (Note: type selection assumes that the lines are ordered alphabetically) 5. scrolling with up and down arrow keys, then doing 1,2 or 3. If the Cancel button is pressed, the string "Cancel" is returned. It requires that the DITL and DLOG resources (1345) packaged with it are in the stack. The dialog is centered on the screen and sized to hold the width of the longest line and/or the prompt line, whichever is widest. It will not overrun the width of a Mac+ screen. INVOKING XScrollBox get XScrollBox(first,prompt,container,userButton) where first is a default selection in the list - either a number or a text string (0 if none). prompt is a string to prompt the user. This appears at the top of the dialog box. container is any hypercard container (field, variable), presumed to be multi-lined. UserButton is the name for an optional author specified button. If this button is pressed, its name is returned further processing by the script. EXAMPLE ex. get XScrollBox(1,"Choose:",card field 1,"Help") if OK is pressed, returns : 1,text of line 1 of card field 1 REVISION HISTORY 1.1 center dialog box on any size screen 1.2 - add selection scrolling by typing and by cursor keys 1.3 - add text of chosen item to return value 1.4 - 3/2/88 add optional user button 1.6 - 5/12/89 fixed problem with selecting the first item the first time when type-selecting. Fixed problem where typing an item exactly selects the one after it. 1.7 - 5/15/89 made it compile under LSC 3.0. 2.0 - 9/9/89 SuperCard compatible, fixed bugs in typing-selection, and userButton string handling. First item is selected if there is no default and the user presses a cursor arrow key. One source for all 3 versions, control version with compiler variables. Compiles under THINK C ™ 4.0. 2.1 - 2/21/90 Push of cancel button now returns "Cancel" string. Fixed some bugs in allocatin and use of return handle. 2.2 - 3/29/90 Correctly displays eight-bit characters. 2.3 - 3/30/90 added ScrollBoxML variation 2.4 - 4/17/90 revived a feature that had disappeared: specifying the default selection in XScrollBox and XScrollBox F as a string rather than a number -- part contents for card part 7 ----- text ----- /* XScrollBox2.3.c */ /* © Digital Medicine Inc. 1988 */ /* written in THINK C™ Version 4.0 © Think Technologies, Inc */ /* version 2.0 by Roger Brown 9/9/88 Dartmouth Courseware Development Group */ /* version 2.3: 3/30/90 Added special request version XScrollBoxML that delimits chosen items by carriage return rather than by line so that items can have commas in them. /* version 2.2: 3/29/90 Control character filter applied to the text in SetUpScrollBox was also filtering out 8 bit characters. Fixed by casting the character to a Byte before testing for < 31. /* version 2.1: 2/21/90 if the cancel button is pressed, the word "Cancel" is returned so we can distinguish between that and pressing OK with no selection made. Also fixed some bugs in allocation and use of ResultHandle global. */ /* version 2 is a major source code change to include all three versions (XScrollBox, XScrollBoxM, and XScrollBoxF) in the same source file with compiler directives to distinguish them. To compile verson set flags ------------------ -------------------- XScrollBox #define VERSION XScrollBox XScrollBox (Multiple Selection, item formatted return) #define VERSION XScrollBoxM XScrollBox (Multiple Selection, line formatted return) #define VERSION XScrollBoxML XScrollBox (list in special font) #define VERSION XScrollBoxF */ /* This is a HyperCard XFCN that creates a scrolling selection dialog box from any multi-lined container. Syntax is: XScrollBox version: ------------------- get XScrollBox(first,prompt,container,userButton) ex. get XScrollBox(1,"Choose:",card field 1,"Help") returns: 1,text of line 1 of card field 1 where first is a default selection in the list - either a number or a text string (0 if none). prompt is a string to prompt the user. This appears at the top of the dialog box. container is any hypercard container (field, variable), presumed to be multi-lined. UserButton is the name for an optional author specified button. If this button is pressed, its name is returned for further processing by the script. Each line of the container is made into a selection line in the dialog. Only one line can be selected. The return value has two items: the number of the selection and the text of the selection. These are separated by commas as in normal HyperCard format. Selection can be made by: 1. double-clicking on a line. 2. single-clicking on a line, then pressing the OK button. 3. single-clicking on a line, then pressing the Return key. 4. typing the first letter(s) of a selection, then doing 1,2, or 3. (Note: type selection assumes that the lines are ordered alphabetically) 5. scrolling with up and down arrow keys, then doing 1,2 or 3. The dialog box is centered in the card window. If the Cancel button or command-period is pressed, a null string is returned. It requires that the DITL and DLOG resources 1345, packaged with it are in the stack. To compile: create a project with this, ANSI-A4 and MacTraps. Build as code resource type XFCN, ID 1345, name XScrollBox. XScrollBoxF version: -------------------- You can specify a special font in which to display the list. get XScrollBoxF(first,prompt,container,userButton,font) ex. get XScrollBoxF(1,"Choose:",card field 1,"Help",courier) returns: 1,text of line 1 of card field 1 where first is a default selection in the list - either a number or a text string (0 if none). prompt is a string to prompt the user. This appears at the top of the dialog box. container is any hypercard container (field, variable), presumed to be multi-lined. UserButton is the name for an optional author specified button. If this button is pressed, its name is returned for further processing by the script. font is an optional font to display the list in. It requires that the DITL and DLOG resources 1347, packaged with it are in the stack. To compile: create a project with this, ANSI-A4, and MacTraps. Build as code resource type XFCN, ID 1347, name XScrollBoxF. XScrollBoxM version: ------------------- Like XScrollBox except that it allows multiple selections. get XScrollBoxM(first,prompt,container,userButton) ex. get XScrollBoxM("1,3,5","Choose:",card field 1,"Help") returns: 1,text of line 1 of card field 1,3,text of line 3 of card field 1, 5,text of line 5 of card field 1 where first is a list of 1 or more default selections in the list - either numbers or an item list of text strings (0 if none). NOTE: the text must exactly match what is in the field! prompt is a string to prompt the user. This appears at the top of the dialog box. container is any hypercard container (field, variable), presumed to be multi-lined. UserButton is the name for an optional author specified button. If this button is pressed, its name is returned for further processing by the script. Each line of the container is made into a selection line in the dialog. Multiple lines can be selected. The return value is an item list in the format: number,text,number,text,..number,text where number is the number of a selection text is the text of the selection with that number It requires that the DITL and DLOG resources 1346, packaged with it are in the stack. To compile: create a project with this, ANSI-A4, and MacTraps. Build as code resource type XFCN, ID 1346, name XScrollBoxM. XScrollBoxML version: ------------------- Like XScrollBoxM except that the return result has one line per item chosen. This makes it easier to handle selection items that have embedded commas. get XScrollBoxML(first,prompt,container,userButton) ex. get XScrollBoxML("1,3,5","Choose:",card field 1,"Help") returns: 1,text of line 1 of card field 1 3,text of line 3 of card field 1 5,text of line 5 of card field 1 where first is a list of 1 or more default selections in the list - either numbers or an item list of text strings (0 if none). NOTE: the text must exactly match what is in the field! prompt is a string to prompt the user. This appears at the top of the dialog box. container is any hypercard container (field, variable), presumed to be multi-lined. UserButton is the name for an optional author specified button. If this button is pressed, its name is returned for further processing by the script. Each line of the container is made into a selection line in the dialog. Multiple lines can be selected. The return value is an item list in the format: number,text number,text .. number,text where number is the number of a selection text is the text of the selection with that number It requires that the DITL and DLOG resources 1348, packaged with it are in the stack. To compile: create a project with this, ANSI-A4, and MacTraps. Build as code resource type XFCN, ID 1348, name XScrollBoxML. */ #include "QuickDraw.h" #include "EventMgr.h" #include "WindowMgr.h" #include "ResourceMgr.h" #include "ControlMgr.h" #include "DialogMgr.h" #include "ListMgr.h" #include "ToolboxUtil.h" #include "HyperXCmd.h" #include "XCmdGlue.inc.c" #include "SetUpA4.h" #define XScrollBox 1 #define XScrollBoxM 2 #define XScrollBoxF 3 #define XScrollBoxML 4 /* specify verson here */ #define VERSION XScrollBox /* utility definitions */ #define FALSE 0 #define TRUE !FALSE #define NULL 0L /* globals */ #define kOKbutton 1 #define kCancel 2 #define kPrompt 3 #define kListItem 4 #define kOutliner 5 #define kUserButton 6 #define kTyping 99 #define kCancelString "Cancel" int kScrollBarWidth = 15; int kStdLDEF = 0; #if VERSION == XScrollBox int kDialogId = 1345; int kStringListId = 1345; #endif #if VERSION == XScrollBoxM int kDialogId = 1346; int kStringListId = 1346; #endif #if VERSION == XScrollBoxF int kDialogId = 1347; int kStringListId = 1347; Str255 gPrompt,fontName; #endif #if VERSION == XScrollBoxML int kDialogId = 1348; int kStringListId = 1348; #endif int gCellWidth; int gCellHeight = 16; Rect dialogRect,listRect,cardRect; ListHandle theList; DialogPtr theListDialog; Str255 theResult,userButton; long theStartWith; Str255 startString; char startIsString; Handle resultHandle; CursHandle theCursor; char collector[32]; int charPos; long charTime; Handle startHandle; int theModifiers; XCmdBlockPtr gParamPtr; /* return max of 2 integers */ max(a,b) int a,b; { if (a>b) return a; return b; } /* return min of 2 integers */ min(a,b) { if (a= string b, else return 1 */ Str255 a,b; int i,compare; SetUpA4(); for (i=0;imodifiers; if ((theEvent->what == keyDown)||(theEvent->what == autoKey)) { theChar = BitAnd(theEvent->message,charCodeMask); if (TickCount() > charTime) charPos = 0; if (BitAnd(theEvent->modifiers,cmdKey)) { /* command key is down */ if (theChar==46) { /* command-period */ *itemHit = 2; GetDItem(theListDialog,kCancel,&iType,&iHandle,&iBox); HiliteControl(iHandle,inButton); result = TRUE; } } else { collector[charPos] = theChar; if ((collector[charPos] ==13)||(collector[charPos]==3)) { /* is CR, use as normal */ *itemHit = 1; GetDItem(theListDialog, kOKbutton, &iType, &iHandle, &iBox); HiliteControl(iHandle,inButton); result = TRUE; } else if ((collector[charPos]==31)||(collector[charPos]==30)) { /* cursor up/down */ VerticalScroll(collector[charPos]); charPos = 0; } else { charPos++; collector[charPos] = 0; *itemHit = kTyping; result = TRUE; charTime = TickCount()+45; } } } RestoreA4(); return result; } #if (VERSION == XScrollBoxM) || (VERSION == XScrollBoxML) /* set up defaults */ SetInitialSelections(maxLines) /* select anything in the starthandle */ int maxLines; { int i,j; Str255 nextItem; Cell aCell,oldCell; char startIsString; long num; i = 1; GetHCItem(*startHandle,i,nextItem); if (strlen(nextItem)==0) return; /* no initial selections */ /* is the first one a string or a number? */ startIsString = TRUE; for (j=0;j0) { CtoPstr((char *)nextItem); /* process a list of numbers */ StringToNum(nextItem,&num); if ((num > 0)&&(numtxFont; myWindow->txFont = systemFont; MoveTo(iBox.left+2,iBox.bottom-4); CtoPstr((char*)gPrompt); DrawString(gPrompt); myWindow->txFont = saveFont; RestoreA4(); } #endif /* Create, size, center, and fill in the selection box. Returns 0 if any errors occur. */ int SetupScrollBox (prompt,theField) char *prompt; char *theField; { Rect dataBounds, itemBox,tempRect; char doVScroll, doHScroll; Point cellSize; Cell aCell,oldCell; int i,j, itemType,x,y; ControlHandle itemHandle; Str255 aString; long len; int fieldLen; int numLines,lineLen,maxLen,row; char done,c; int screenCenterX,screenCenterY; int dialogWidth; int dialogCenterX,dialogCenterY; int itemWidth,itemHeight; int itemHit; GrafPtr gp; Handle tempHandle; int numButtons,cWidth; #if VERSION == XScrollBoxF int theFont; strcpy(gPrompt,prompt); #endif if (strlen(userButton)>0) numButtons = 3; else numButtons = 2; cWidth = CharWidth('m'); /* size the dialog box */ dialogWidth = 200+cWidth*strlen(userButton); /* minimum width to fit buttons at bottom */ /* make sure the prompt fits */ dialogWidth = max(dialogWidth,strlen(prompt)*cWidth+20); /* find the longest line */ lineLen = maxLen = numLines = 0; fieldLen = strlen(theField); for (i=0;i 31) { aString[j] = theField[i]; j++; } if ((theField[i] ==13)||(i==(fieldLen-1))) { aString[j] = 0; SetPt(&aCell,0,row); row ++; lineLen = strlen(aString); LSetCell(&aString[0], lineLen, aCell, theList); j = 0; } } #if (VERSION == XScrollBoxM) || (VERSION == XScrollBoxML) SetInitialSelections(numLines); #else if (startIsString) { SetPt(&oldCell,0,0); LGetSelect(TRUE,&oldCell,theList); /* get current selection */ SetPt(&aCell,0,0); if (LSearch(startString,strlen(startString),MySelect,&aCell,theList)) { if (!EqualPt(oldCell,aCell)) { LSetSelect(FALSE,oldCell,theList); /* clear current selection */ LSetSelect(TRUE,aCell,theList); /* set the new one */ LAutoScroll(theList); } } } else if ((theStartWith > 0)&&(theStartWith10) LAutoScroll(theList); } #endif LDoDraw(TRUE, theList); /* now complete the two user items of the dialog */ itemBox = listRect; itemBox.right = itemBox.right + kScrollBarWidth; SetDItem(theListDialog, kListItem, userItem, DrawListItem, &itemBox); GetDItem(theListDialog,kOKbutton,&itemType,&itemHandle,&itemBox); SetDItem(theListDialog, kOutliner, userItem + itemDisable, OutlineButton, &itemBox); #if VERSION == XScrollBoxF /* install the font */ if (strlen(fontName) > 0) { CtoPstr((char*)fontName); GetFNum(fontName,&theFont); if (theFont>0) theListDialog->txFont = theFont; } #endif /* present the window up front */ ShowWindow(theListDialog); BringToFront(theListDialog); return 1; } -- part contents for card part 11 ----- text ----- DoListDialog () /* pose the dialog and handle it */ { int itemHit; Point aPoint; Cell oldCell,aCell; Boolean somethingSelected,found; Str255 temp; itemHit = charPos = 0; while (1) { RememberA4(); ModalDialog(NameSelect, &itemHit); switch (itemHit) { case kOKbutton : return 1; break; case kCancel: return -1; break; case kListItem: SetPort(theListDialog); GetMouse(&aPoint); if (LClick(aPoint, theModifiers, theList)) return 1; break; case kUserButton: return 2; break; case kTyping: SetPt(&oldCell,0,0); /* get current selection */ somethingSelected = LGetSelect(TRUE,&oldCell,theList); SetPt(&aCell,0,0); RememberA4(); found = LSearch(collector,strlen(collector),MySelect,&aCell,theList); if (found==TRUE) { if ((somethingSelected==FALSE) || (!EqualPt(oldCell,aCell))) { LSetSelect(FALSE,oldCell,theList); /* clear current selection */ LSetSelect(TRUE,aCell,theList); /* set the new one */ LAutoScroll(theList); } } break; } } } GetListSelections(aHandle) Handle aHandle; /* get the text of the selection made */ { char someSelect; Cell aCell; int stringLength,t,b,i; Str255 num,theText; long n,len; SetPt(&aCell, 0, 0); HLock(aHandle); strcpy(*aHandle,""); someSelect = LGetSelect(TRUE, &aCell, theList); while (someSelect==TRUE) { stringLength = 255; LGetCell(theText, &stringLength, aCell, theList); n = aCell.v+1; theText[stringLength] = 0; NumToString(n,num); PtoCstr((char *)num); strcat(num,","); strcat(num,theText); #if VERSION == XScrollBoxML strcat(num,"\15"); /* divide into lines */ #else strcat(num,","); #endif len = GetHandleSize(aHandle); len = len + strlen(num); HUnlock(aHandle); SetHandleSize(aHandle,len); HLock(aHandle); strcat(*aHandle,num); aCell.v++; someSelect = LGetSelect(TRUE, &aCell, theList); } len = GetHandleSize(aHandle); if (len>0) { HUnlock(aHandle); SetHandleSize(aHandle,len-1); /* clip off last comma */ *(*aHandle+len-2) = 0; HLock(aHandle); } } /* clean up memory */ PrepareToExit() { if (theList != NULL) LDispose(theList); if (theListDialog != NULL) DisposDialog(theListDialog); } /* create scroll box, present it, return user's selection */ pascal void DoScrollBox(paramPtr) XCmdBlockPtr paramPtr; { Ptr thePrompt; Ptr theField; Ptr theUserButton; int status,i; Size len; resultHandle = NewHandle(2); if (paramPtr->paramCount < 3) { SetHandleSize(resultHandle,255); #if VERSION == XScrollBox strcpy(*resultHandle,"Not enough parameters in XScrollBox"); #endif #if VERSION == XScrollBoxM strcpy(*resultHandle,"Not enough parameters in XScrollBoxM"); #endif #if VERSION == XScrollBoxML strcpy(*resultHandle,"Not enough parameters in XScrollBoxML"); #endif #if VERSION == XScrollBoxF strcpy(*resultHandle,"Not enough parameters in XScrollBoxF"); #endif } else { theCursor = GetCursor(watchCursor); SetCursor(*theCursor); for (i=0;iparamCount;i++) { MoveHHi(paramPtr->params[i]); HLock(paramPtr->params[i]); } startHandle = paramPtr->params[0]; startIsString = TRUE; strcpy(startString,*startHandle); #if (VERSION != XScrollBoxM) && (VERSION != XScrollBoxML) for (i=0;iparams[1]); theField = *(paramPtr->params[2]); theUserButton = *(paramPtr->params[3]); if (GetHandleSize(paramPtr->params[3])>0) strcpy(userButton,theUserButton); else strcpy(userButton,""); #if VERSION == XScrollBoxF fontName[0] = 0; if (paramPtr->paramCount > 4) { strcpy(fontName,*(paramPtr->params[4])); } #endif GetCardRect(&cardRect); status = SetupScrollBox(thePrompt,theField); InitCursor(); if (status==1) { status = DoListDialog(); if (status==1) GetListSelections(resultHandle); else if (status==2) { SetHandleSize(resultHandle,1+strlen(userButton)); strcpy(*resultHandle,userButton); } else if (status==-1) { strcpy(userButton,kCancelString); SetHandleSize(resultHandle,1+strlen(userButton)); strcpy(*resultHandle,userButton); } else strcpy(*resultHandle,""); } else #if VERSION == XScrollBox strcpy(*resultHandle, "Can't find dialog resource 1345 for XScrollBox XFCN"); #endif #if VERSION == XScrollBoxM strcpy(*resultHandle, "Can't find dialog resource 1346 for XScrollBoxM XFCN"); #endif #if VERSION == XScrollBoxF strcpy(*resultHandle, "Can't find dialog resource 1347 for XScrollBox XFCN"); #endif #if VERSION == XScrollBoxML strcpy(*resultHandle, "Can't find dialog resource 1348 for XScrollBoxML XFCN"); #endif } paramPtr->returnValue = resultHandle; for (i=0;iparamCount;i++) HUnlock (paramPtr->params[i]); return; } /* this is the entry point for the XFCN */ pascal void main(paramPtr) XCmdBlockPtr paramPtr; { RememberA0(); SetUpA4(); gParamPtr = paramPtr; DoScrollBox(paramPtr); /* run the main event loop */ PrepareToExit(); /* tidy up */ RestoreA4(); /* and this also */ return; }